package com.vst.orm.search.hibernate;


import java.io.Serializable;
import org.hibernate.EntityMode;
import org.hibernate.SessionFactory;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.CollectionType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;

import com.vst.orm.search.Metadata;

public class HibernateNonEntityMetadata implements Metadata {
	private SessionFactory sessionFactory;
	private Type type;
	private Class<?> collectionType;

	public HibernateNonEntityMetadata(SessionFactory sessionFactory, Type type, Class<?> collectionType) {
		this.sessionFactory = sessionFactory;
		this.type = type;
		this.collectionType = collectionType;
	}

	public String getIdProperty() {
		return null;
	}

	public Metadata getIdType() {
		return null;
	}

	public Serializable getIdValue(Object object) {
		return null;
	}

	public Class<?> getJavaClass() {
		return this.type.getReturnedClass();
	}

	public String[] getProperties() {
		if (this.type.isComponentType()) {
			return ((ComponentType) this.type).getPropertyNames();
		}
		return null;
	}

	public Metadata getPropertyType(String property) {
		if (!this.type.isComponentType()) {
			return null;
		}
		int i = getPropertyIndex(property);
		if (i == -1) {
			return null;
		}
		Type pType = ((ComponentType) this.type).getSubtypes()[i];
		Class<?> pCollectionType = null;
		if (pType.isCollectionType()) {
			pType = ((CollectionType) pType).getElementType((SessionFactoryImplementor) this.sessionFactory);
			pCollectionType = pType.getReturnedClass();
		}
		if (pType.isEntityType()) {
			return (Metadata) new HibernateEntityMetadata(this.sessionFactory,
					this.sessionFactory.getClassMetadata(((EntityType) pType).getName()), pCollectionType);
		}
		return new HibernateNonEntityMetadata(this.sessionFactory, pType, pCollectionType);
	}

	public Object getPropertyValue(Object object, String property) {
		if (!this.type.isComponentType()) {
			return null;
		}
		int i = getPropertyIndex(property);
		if (i == -1) {
			return null;
		}
		return ((ComponentType) this.type).getPropertyValue(object, i, EntityMode.POJO);
	}

	public boolean isCollection() {
		return this.collectionType != null;
	}

	public Class<?> getCollectionClass() {
		return this.collectionType;
	}

	public boolean isEmeddable() {
		return this.type.isComponentType();
	}

	public boolean isEntity() {
		return false;
	}

	public boolean isNumeric() {
		return Number.class.isAssignableFrom(getJavaClass());
	}

	public boolean isString() {
		int[] types = this.type.sqlTypes((Mapping) this.sessionFactory);
		return (types.length == 1) && ((types[0] == 12) || (types[0] == 1));
	}

	private int getPropertyIndex(String property) {
		String[] properties = getProperties();
		for (int i = 0; i < properties.length; i++) {
			if (properties[i].equals(property)) {
				return i;
			}
		}
		return -1;
	}
}
